<template>
    <div class="PickBox">
        <div class="svPanel" ref="svEle" @mousedown="SvPaneMousedown">
            <div class="color" :style="{
                backgroundColor: `hwb(${hsvColor[0]} 0 0)`,
            }"></div>
            <div class="white"></div>
            <div class="black"></div>
            <div class="white2"></div>
            <div class="Naker" :style="{
                transform: `translate(${svPanelPosition.x}px,${svPanelPosition.y}px)`,
                backgroundColor: hsvStyle,
            }"></div>
        </div>
        <div class="alphaBar" ref="alphaEle" @mousedown="AlphaBarMousedown">
            <div class="alphaBarColor" :style="{
                background: `linear-gradient(to top, ${AlphaColor}00, ${AlphaColor}ff)`
            }"></div>
            <div class="Bar" :style="{
                transform: `translate(0px,${alphaBarPosition.y}px)`,
                backgroundColor: hsvStyle,
            }"></div>
        </div>
        <div class="hueBar" ref="hueEle" @mousedown="HueBarMousedown">
            <div class="Bar" :style="{
                transform: `translate(0px,${hueBarPosition.y}px)`,
                backgroundColor: `hwb(${hsvColor[0]} 0 0)`,
            }"></div>
        </div>
    </div>
    <div class="ValueBox">
        <a-button class="button" :style="{ background: Value, transition: 'none', pointerEvents: 'none' }"></a-button>
        <a-input id="" name="ColorChoose" class="ValueInput" @change="SetColor(Value)" v-model:value="Value"></a-input>
        <a-tooltip placement="top" title="保存色板">
            <a-button class="button" @click="AddColors">
                <template #icon>
                    <span class="C-Icon">&#xe713;</span>
                </template>
            </a-button>
        </a-tooltip>
    </div>
    <div class="ColorBox">
        <div class="title">默认色板</div>
        <div class="Content">
            <ColorItem :ColorMap="ColorMap" :ShowClose="false" />
        </div>
    </div>
    <div class="ColorBox" v-if="ColorCache.length">
        <div class="title">保存色板</div>
        <div class="Content">
            <ColorItem :ColorMap="ColorCache" :ShowClose="true" />
        </div>
    </div>
</template>
<script setup>
import ColorEvent from './ColorEvent.js'
import { Badge } from 'ant-design-vue'
import { CloseOutlined } from '@ant-design/icons-vue'
import { computed, nextTick, onMounted, inject, onUnmounted, ref, watch, h } from 'vue';
const StateEvent = inject('StateEvent');
const ColorCache = StateEvent.CacheData.value.ColorCache;


function AddColors() {
    StateEvent.SetColorCache(Value.value);
}



function ColorItem(props) {
    var child = [];
    for (const key in props.ColorMap) {
        const element = props.ColorMap[key];
        if (props.ShowClose) {
            child.push(h('div',
                { class: 'ColorItem', onClick: () => { SetColorHandle(element) } },
                h(Badge, {}, {
                    default: () => h('div', { class: 'Color', title: key, style: { backgroundColor: element } }),
                    count: () => h(CloseOutlined, {
                        class: 'CloseColor', onClick: (e) => {
                            e.stopPropagation();
                            StateEvent.DeleteColorCache(key)
                        }
                    })
                })
            ));
        } else {
            child.push(h('div',
                { class: 'ColorItem', onClick: () => { SetColorHandle(element) } },
                h('div', { class: 'Color', title: key, style: { backgroundColor: element } })
            ));
        }
    };
    return child;
}
ColorItem.props = ['ColorMap', 'ShowClose']


const ColorMap = ref({
    white: '#ffffff',
    black: '#000000d9',
    gray: '#d9d9d9',
    blue: '#1677ff',
    purple: '#722ED1',
    cyan: '#13C2C2',
    green: '#52C41A',
    magenta: '#EB2F96',
    pink: '#eb2f96',
    red: '#F5222D',
    orange: '#FA8C16',
    yellow: '#FADB14',
    volcano: '#FA541C',
    geekblue: '#2F54EB',
    gold: '#FAAD14',
    lime: '#A0D911'
});

const svEle = ref();
const alphaEle = ref();
const hueEle = ref();

const props = defineProps(['value']);
const Value = ref('#ff0000');
const emits = defineEmits(['ChangeColor'])

let MoveState = null;
let svPanelRect;
let alphaBarRect;
let hueBarRect;


const svPanelPosition = ref({ x: 198, y: 0 });
const alphaBarPosition = ref({ y: 0 });
const hueBarPosition = ref({ y: 0 });

const hsvColor = ref([0, 100, 100]);
const hsvStyle = ref('');

const alphaValue = ref('');

const _color = new ColorEvent();
hsvStyle.value = _color.RGB;

let changeFilg = true;

const AlphaColor = computed(() => {
    return hsvStyle.value.substring(0, 7);
});

watch(hsvColor, () => {
    _color.setHSB(hsvColor.value[0], hsvColor.value[1], hsvColor.value[2]);
    hsvStyle.value = _color.RGB;
    if (!changeFilg) return;
    Value.value = _color.RGB + alphaValue.value;
}, { deep: true });

const SetPosition = function (h, s, b) {
    const hueHeight = 124;
    hueBarPosition.value.y = parseInt(h / 360 * (hueHeight - 3));
    svPanelPosition.value.x = (s / 100) * (200 - 4) + 2
    svPanelPosition.value.y = (100 - b) / 100 * (124 - 4) + 2;

    changeFilg = false;
    hsvColor.value = [_color.h, _color.s, _color.b];
    nextTick(() => {
        changeFilg = true;
    })
}

watch(alphaValue, () => {
    Value.value = _color.RGB + alphaValue.value;
})

const SetColorHandle = function (color) {
    SetColor(color);
    Value.value = color;
    emits('ChangeColor', color);
};

const SetColor = function (color) {
    if (/^#([0-9a-f]{3})$/i.test(color)) {
        var _c = color.replace('#', '').split('');
        _color.setRGB(`#${_c[0]}${_c[0]}${_c[1]}${_c[1]}${_c[2]}${_c[2]}`);
        SetPosition(_color.h, _color.s, _color.b);
    } else if (/^#([0-9a-f]{6})$/i.test(color)) {
        _color.setRGB(color);
        SetPosition(_color.h, _color.s, _color.b);
        alphaValue.value = color.substring(8, 9);
    } else if (/^#([0-9a-f]{8})$/i.test(color)) {
        _color.setRGB(color.substring(0, 7));
        SetPosition(_color.h, _color.s, _color.b);
        var opacity = parseInt(color.substring(7, 9), 16) / 255;
        alphaBarPosition.value.y = (1 - opacity) * (124 - 4);
    };

}

onMounted(() => {
    Value.value = props.value;
    SetColor(props.value)
})


defineExpose({ SetColor })


const SvPaneMousedown = function (e) {
    svPanelRect = svEle.value.getBoundingClientRect();
    MoveState = 'SvPanel';
    document.addEventListener('mousemove', MoveEvent, true);
    document.addEventListener('mouseup', MouseUp, true);
    MoveEvent(e);
}
const AlphaBarMousedown = function (e) {
    alphaBarRect = alphaEle.value.getBoundingClientRect();
    MoveState = 'AlphaBar';
    document.addEventListener('mousemove', MoveEvent, true);
    document.addEventListener('mouseup', MouseUp, true);
    MoveEvent(e);
}

const HueBarMousedown = function (e) {
    hueBarRect = hueEle.value.getBoundingClientRect();
    document.addEventListener('mousemove', MoveEvent, true);
    document.addEventListener('mouseup', MouseUp, true);
    MoveState = 'HueBar';
    MoveEvent(e);
}

const MouseUp = function (e) {
    MoveState = null;
    document.removeEventListener('mousemove', MoveEvent, true);
    document.removeEventListener('mouseup', MouseUp, true);
    MoveEvent(e);
    nextTick(() => {
        emits('ChangeColor', Value.value);
    })
}
function toHex(colorValue) {
    const hex = colorValue.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
};
const MoveEvent = function (e) {
    if (MoveState === null) return;
    const x = e.pageX, y = e.pageY;
    let Rect, position;
    if (MoveState == 'SvPanel') {
        Rect = svPanelRect;
        position = svPanelPosition;
        let _x = x - Rect.left;

        if (_x < 2) { _x = 2; }
        else if (_x > Rect.width - 2) { _x = Rect.width - 2; };
        position.value.x = _x;

        let _y = y - Rect.top;
        if (_y < 2) { _y = 2; }
        else if (_y > Rect.height - 2) { _y = Rect.height - 2; };
        position.value.y = _y;

        hsvColor.value[1] = parseInt((_x - 2) / (Rect.width - 4) * 100)
        hsvColor.value[2] = 100 - (parseInt((_y - 2) / (Rect.height - 4) * 100))

    } else if (MoveState == 'AlphaBar') {
        Rect = alphaBarRect;
        position = alphaBarPosition;
        let _y = y - Rect.top;
        if (_y < 0) { _y = 0; }
        else if (_y > Rect.height - 3) { _y = Rect.height - 3; };
        position.value.y = _y;

        let alpha = toHex(parseInt((1 - _y / (Rect.height - 3)) * 255))

        if (alpha == 'ff') {
            alphaValue.value = ''
        } else {
            alphaValue.value = alpha;
        }
    } else if (MoveState == 'HueBar') {
        Rect = hueBarRect;
        position = hueBarPosition;
        let _y = y - Rect.top;
        if (_y < 0) { _y = 0; }
        else if (_y > Rect.height - 3) { _y = Rect.height - 3; };
        position.value.y = _y;
        hsvColor.value[0] = parseInt(_y / (Rect.height - 3) * 360)
    };

};

onUnmounted(() => {
    document.removeEventListener('mousemove', MoveEvent, true);
    document.removeEventListener('mouseup', MouseUp, true);
})



</script>
<style lang="less">
.PickBox {
    width: 100%;
    height: 140px;
    padding: 8px;
    display: flex;
    user-select: none;

    .svPanel {
        flex: none;
        width: 200px;
        height: 124px;
        position: relative;
        box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4);

        >div.white,
        >div.black,
        >div.color,
        >div.white2 {
            pointer-events: none;
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
        }

        .color {
            background-color: hsv(0, 42, 29);
        }

        .black {
            background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));

        }

        .white {
            background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));

        }

        .white2 {
            background-image: radial-gradient(circle at left top, #fff, rgba(255, 255, 255, 0));
            opacity: 0.2;
        }

        .Naker {
            pointer-events: none;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            border: 1px solid #666;
            background-color: #0f0;
            position: absolute;
            margin: -5px 0 0 -5px;
            box-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
        }
    }

    .Bar {
        width: 28px;
        border: 1px solid #ccc;
        margin: 0 0 0 -2px;
        height: 4px;
    }

    .hueBar {
        flex: none;
        margin-left: 8px;
        width: 24px;
        height: 124px;
        background: linear-gradient(to bottom, #f00 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
        box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4);
    }

    .alphaBar {
        flex: none;
        margin-left: 8px;
        width: 24px;
        height: 124px;
        background-image: url();
        box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4);
        position: relative;

        .alphaBarColor {
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
    }
}


.ValueBox {
    border-top: 1px solid #d9d9d9;
    padding: 8px;
    display: flex;
    justify-content: space-between;
    flex-direction: row;
    flex-wrap: wrap;

    .ValueInput {
        width: 180px;
    }
}

.ColorBox {
    padding: 12px 0;
    border-top: 1px solid #d9d9d9;

    .title {
        width: 100%;
        height: 16px;
        line-height: 16px;
        margin-bottom: 4px;
        padding-left: 8px;
    }

    .Content {
        display: flex;
        justify-content: flex-start;
        flex-wrap: wrap;
    }

    .ColorItem {
        cursor: pointer;
        margin: 2px;
        padding: 4px;

        .Color {
            border-radius: 4px;
            box-shadow: 0 0 3px rgba(0, 0, 0, 0.4);
            width: 20px;
            height: 20px;
        }
    }
}

.CloseColor {
    font-size: 10px;
    background-color: #f00;
    border: 1px solid #ccc;
    border-radius: 50%;
    padding: 2px;
    color: #fff;
    cursor: pointer;
}
</style>